<?php
/**
 * this is auth of 3K-SDK 
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the MIT-LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @author lane<61647649@qq.com>
 * @copyright lane<61647649@qq.com>
 * @link http://www.3k.com
 * @license http://www.opensource.org/licenses/mit-license.php MIT License
 */

// defined('CORE') or exit('Request Error!');

/**
 * cls_3k_auth 对等加密
 * 
 * @author lane<61647649@qq.com> 
 */
class cls_3k_auth
{
    private function __construct() {  
    }

    private static $_chars = array(
        '0', 'a', 'q', '1', 'b', 's', '2', 'r', 'c',
        '3', 't', 'd', '4', 'u', 'e', '5', 'g', 'v',
        '6', 'f', 'p', '7', 'h', 'w', '8', 'o', 'x',
        '9', 'i', 'j', 'k', 'l', 'm', 'n', 'y', 'z'
    );

    private static $_rand = ''; // 随机字符串
    private static $_key = '';  // 秘钥

    /**
     * 初始化, $_rand 随机
     * $length  随机多少位
     */
    private static function _init_rand($length = 10, $pos = 2)
    {
        if (empty(self::$_rand)) 
        {
            shuffle(self::$_chars);
            $tmp = array_slice(self::$_chars, 0, $length);
            self::$_rand = implode('', $tmp);

            // 生成Key
            self::$_key = '';
            $md5_value = str_split(md5(self::$_rand, false), 1);
            $i = 0;
            do 
            {
                $index = $i % count($md5_value);
                self::$_key .= $md5_value[$index];
                $i += $pos;
            } while (strlen(self::$_key) < 16);
        }
    }

    /**
     * 获取KEY
     */
    public static function get_key($length = 10, $pos = 2)
    {
        self::_init_rand($length, $pos);
        return self::$_key;
    }

    /**
     * 获取随机字符串, 如果随机字符串已经生成，就不要再生成了
     */
    public static function get_rand($length = 10, $pos = 2)
    {
        self::_init_rand($length, $pos);
        return self::$_rand;
    }

    /**
     * 手动设置随机字符串, 当重新设置rand需要强制初始化一次key
     * $pos 读取key的步长
     */
    public static function set_rand($rand, $pos = 2)
    {
        self::$_rand = $rand;

        // 生成Key
        self::$_key = '';
        $md5_value = str_split(md5(self::$_rand, false), 1);
        $i = 0;
        do 
        {
            $index = $i % count($md5_value);
            self::$_key .= $md5_value[$index];
            $i += $pos;
        } while (strlen(self::$_key) < 16);
    }

    /**
     * 反量
     */
    private static function _iv()
    {
        self::_init_rand();
        $iv  = '';
        $arr = str_split(self::$_key, 1);
        for ($i = count($arr) - 1; $i >= 0; $i--)
        {
            $iv .= $arr[$i];
        }
        return $iv;
    }

    /**
     * 加密
     * plaintext 明文
     * pos 步长
     * rand 随机数
     */
    public static function encrypt($plaintext, $rand = '', $pos = 2)
    {
        if (!empty($rand)) 
        {
            self::set_rand($rand, $pos);
        }

        $plaintext = trim($plaintext);
        $iv        = self::_iv();
        $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, self::$_key, $plaintext, MCRYPT_MODE_CBC, $iv);
        $encrypted = bin2hex($encrypted);
        $encrypted = trim(strtoupper($encrypted));
        return array('rand' => self::$_rand, 'key' => self::$_key, 'e' => $encrypted);
    }

    /**
     * ciphertext 密文
     * pos 步长
     * rand 随机数
     */
    public static function dencrypt($ciphertext, $rand = '', $pos = 2)
    {
        if (!empty($rand)) 
        {
            self::set_rand($rand, $pos);
        }

        $ciphertext    = trim($ciphertext);
        $iv            = self::_iv();
        $encryptedData = pack('H*', $ciphertext);
        $decrypted     = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, self::$_key, $encryptedData, MCRYPT_MODE_CBC, $iv);
        $decrypted     = trim($decrypted);
        return array('rand' => self::$_rand, 'key' => self::$_key, 'd' => $decrypted);
    }
}
